import pymongo
from bson.code import Code
from bson.son import SON
from blw.mapper_url import MapperUrl
import re
from blw.settings import MONGO_DB
from os import environ

# Helper lambda for gracefully degrading environmental variables:
env = lambda e, d: environ[e] if environ.has_key(e) else d
default_database = env('DJANGO_DATABASE', 'default')
print MONGO_DB[default_database]
print default_database
url= MONGO_DB[default_database]['url']
dbName = MONGO_DB[default_database]['dbName']




class MongoHelper():
    
    def __init__(self):
        self.conn = pymongo.Connection(url)
        print self.conn
        self.db = self.conn[dbName]
        print self.db.collection_names()
    
    def addPageCrawler(self, dumpData):
        try:
            self.db.pages.insert(dumpData, safe=True)
            print "document was added on db.pages."
        except Exception, e:
            print str(e)
            
    def getDocumentsByUrl(self, url):
        return self.db.colls.find({'url':{'$in':[url]}}).sort([('creation_date', pymongo.DESCENDING)])
    
    def dropDocumentsByUrl(self, url):
        self.db.colls.remove({'url':url})
        print "All documents were deleted with contains the following URL %s" % url
        
    def saveDocument(self, doc):
        self.db.colls.save(doc)
        print "document was updated on db.colls."
    
    def dropCollectionColls(self,dbname):
        self.db.drop_collection(dbname)
        print "Colls was dropped."
    
    
    def findCategories(self,dictionary=None):
        reducer = Code(""" function(obj, prev){ prev.count++; prev.slug=obj.cat;  }""")
        if dictionary != None and dictionary.has_key('tags') and  not dictionary['tags'].has_key('$all'):
            dictionary.update({ 'tags': { '$all': self.getRegex(dictionary['tags']) } })
        categories = self.db.pages.group(key={"category":'Recursos Humanos'},condition=dictionary, initial={"count": 0,"slug":''}, reduce=reducer)
        def notNone(x):
            if x['category'] != None:
                x['count'] = int(x['count'])
                if dictionary != None:
                    slug = MapperUrl().createUrlFilter('cat',dictionary)
                    x['slug'] =  slug.replace('<value>',x['slug'])
                else :
                    x['slug'] = 'cat_' + x['slug']
                return x
        unOrderedList= map(notNone,categories)
        return sorted(unOrderedList,key=lambda category: category['count'],reverse=True)
    
    def findDates(self,dictionary=None):
        reducer = Code(""" function(obj, prev){ prev.count++;prev.slug=obj.date;  }""")
        if dictionary != None and dictionary.has_key('tags') and  not dictionary['tags'].has_key('$all'):
            dictionary.update({ 'tags': { '$all': self.getRegex(dictionary['tags']) } })
        results = self.db.pages.group(key={"date":True}, condition=dictionary, initial={"count": 0,"slug":''}, reduce=reducer)
        def notNone(x):
            if x['date'] != None:
                x['count'] = int(x['count'])
                if dictionary != None:
                    slug = MapperUrl().createUrlFilter('date',dictionary)
                    x['slug'] =  slug.replace('<value>',x['slug'])
                else :
                    x['slug'] = 'date_' + x['slug']
                return x
        unOrderedList= map(notNone,results)
        return sorted(unOrderedList,key=lambda date: date['count'],reverse=True)
    
    def findZones(self,dictionary=None):
        
        mapper = Code("""
                   function () {
                     this.zones.forEach(function(z) {
                       emit(z, 1);
                     });
                   }
                   """)
        reducer = Code("""
                    function (key, values) {
                      var total = 0;
                      for (var i = 0; i < values.length; i++) {
                        total += values[i];
                      }
                      return total;
                    }
                    """)
        if dictionary != None and dictionary.has_key('tags') and  not dictionary['tags'].has_key('$all'):
            dictionary.update({ 'tags': { '$all': self.getRegex(dictionary['tags']) } })
        results = self.db.pages.map_reduce(mapper, reducer, "zoneresults",query=dictionary)
        def groupByZone(doc):
            slugByZone =  'zones.desc_' +  doc['_id']['desc']
            if dictionary != None:
                    slug = MapperUrl().createUrlFilter('zones.desc',dictionary)
                    slugByZone =  slug.replace('<value>', doc['_id']['desc'])
            return {u'zone': doc['_id']['description'], u'count': int(doc['value']), u'slug': slugByZone }
        resultsGrouped= map(groupByZone,results.find())
        return sorted(resultsGrouped,key=lambda zone: zone['count'],reverse=True)
        
    
    def findSubZones(self,dictionary=None):
        
        mapper = Code("""
                   function () {
                     this.szones.forEach(function(z) {
                       emit(z, 1);
                     });
                   }
                   """)
        reducer = Code("""
                    function (key, values) {
                      var total = 0;
                      for (var i = 0; i < values.length; i++) {
                        total += values[i];
                      }
                      return total;
                    }
                    """)
        if dictionary != None and dictionary.has_key('tags') and  not dictionary['tags'].has_key('$all'):
            dictionary.update({ 'tags': { '$all': self.getRegex(dictionary['tags']) } })
        results = self.db.pages.map_reduce(mapper, reducer, "subzonesresults",query=dictionary)
        def groupBySubZone(doc):
            slugBySZone =  'szones.desc_' + doc['_id']['desc']
            if dictionary != None:
                    slug = MapperUrl().createUrlFilter('szones.desc',dictionary)
                    slugBySZone =  slug.replace('<value>', doc['_id']['desc'])
            return {u'szone': doc['_id']['description'], u'count': int(doc['value']), u'slug': slugBySZone}
        resultsGrouped= map(groupBySubZone,results.find())
        return sorted(resultsGrouped,key=lambda zone: zone['count'],reverse=True)
    
    
    
    def findLastAdJob(self):
        return self.db.pages.find().sort([('creation_date', pymongo.DESCENDING)]).limit(40)
    
    def findBy(self,dictionary):
        if dictionary.has_key('tags'):
            dictionary.update({ 'tags': { '$all': self.getRegex(dictionary['tags']) } })
        return self.findQueryPage(dictionary,limit=40)
    
    def findQueryPage(self,query,limit):
        return self.db.pages.find(query).sort([('creation_date',pymongo.DESCENDING)]).limit(limit)
    
    def findWord(self,preffixWord,limit):
        import re
        regx = re.compile('^' + preffixWord, re.IGNORECASE)
        return self.db.words.find({'_id':{'$regex': regx}}).sort([('value',pymongo.DESCENDING)]).limit(limit)

    def countingWord(self):
        mapper = Code("""
                   function () {
                     this.tags.forEach(function(z) {
                       emit(z, 1);
                     });
                   }
                   """)
        reducer = Code("""
                    function (key, values) {
                      var total = 0;
                      for (var i = 0; i < values.length; i++) {
                        total += values[i];
                      }
                      return total;
                    }
                    """)
        return self.db.pages.map_reduce(mapper, reducer, "words",query={})
        
    def getRegex(self, words):
        if words :
            import urllib 
            splitWords = re.findall(r"[\w']+", urllib.unquote(words).decode('utf8'))
            return splitWords
        else :
            return None
        
if __name__ == '__main__':
    mongoUtil=MongoHelper()
    #result = mongoUtil.countingWord()
    result = mongoUtil.findWord('java',10)
    print 'result'
    for doc in result:
        print doc
